package com.techfort.affs.mongoclient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;


public class MongolabClient {

	private String apiKey;
	private String database;
	private String currentCollection;
	private static final String PROTOCOL = "https";
	private static final String SERVER = "mongolab.com";
	private static final int PORT = 443;
	private String encoding = "UTF-8";
	private HttpClient client = new DefaultHttpClient();
	
	
	public MongolabClient(String database, String collection, String apiKey){
		this.database = database;
		this.currentCollection = collection;
		this.apiKey = apiKey;
	}
	
	public void setCurrentCollection(String collection){
		this.currentCollection = collection;
	}
	
	public void setEncoding(String encoding){
		this.encoding = encoding;
	}
	
	private String getApiUrl(){
		return "api/1/databases/" + database + "/collections/" + currentCollection;
	}
	
	private URI createURI(List<NameValuePair> qparams, String apiUrl) throws URISyntaxException{
		return URIUtils.createURI(PROTOCOL, SERVER, PORT, apiUrl, URLEncodedUtils.format(qparams, encoding), null);
	}
	
	public JSONObject insert(JSONObject object){
		
		try {
			String query = getApiUrl();
			List<NameValuePair> qparams = new ArrayList<NameValuePair>();
			qparams.add(new BasicNameValuePair("apiKey", apiKey));
			
			URI uri = createURI(qparams, query);
			HttpPost post = new HttpPost(uri);
			post.setHeader("Content-type","application/json");
			Log.i("INFO", object.toString());
			post.setEntity(new StringEntity(object.toString()));
			HttpResponse response = client.execute(post);
			return new JSONObject(getResponse(response));
			
		} catch (URISyntaxException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	
	public JSONObject update(JSONObject json) {
		
		JSONObject id;
		try {
			id = (JSONObject) json.get("_id");
			
			return update(id.getString("$oid"), json);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	return null;
    	
        
	}
	
	public JSONObject update(String str_id, JSONObject json){
		try {
        	
        	String query = getApiUrl() + "/" + str_id;
        	
    		List<NameValuePair> qparams = new ArrayList<NameValuePair>();
            qparams.add(new BasicNameValuePair("apiKey", apiKey));
            
            URI uri = createURI(qparams, query);
            
            HttpPut put = new HttpPut(uri);
        	StringEntity se = new StringEntity(json.toString());
        	put.setEntity(se);
            put.setHeader("Content-type", "application/json");
            
            HttpResponse response = client.execute(put);
        	return new JSONObject(getResponse(response));
        	
        } catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public JSONObject get(String id) {
		
		try {
			String search = getApiUrl() + "/" + id;
			
			List<NameValuePair> qparams = new ArrayList<NameValuePair>();
	        qparams.add(new BasicNameValuePair("apiKey", apiKey));
	        
	        URI uri = createURI(qparams, search);
	        
	        HttpGet req = new HttpGet(uri);
	        HttpResponse response = client.execute(req);
			String json = getResponse(response);
			
			return new JSONObject(json);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return null;
		
	}
	
	public JSONArray list(List<NameValuePair> qparams){
		/* example query:
		 * qparams.add(new BasicNameValuePair("q", "{ \"active\":\"yes\" }"));
		 * returns all documents with an "active" field with value "yes" 
		 */
		
		try {
			String search = getApiUrl();
			
	        qparams.add(new BasicNameValuePair("apiKey", apiKey));
	        
	        URI uri = createURI(qparams, search);
	        
	        HttpGet req = new HttpGet(uri);
	        HttpResponse response = client.execute(req);
			String json = getResponse(response);
			
			return new JSONArray(json);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public JSONObject findOne(List<NameValuePair> qparams){
		try {
			String search = getApiUrl();
			
	        qparams.add(new BasicNameValuePair("apiKey", apiKey));
	        qparams.add(new BasicNameValuePair("fo", "true"));
	        
	        URI uri = createURI(qparams, search);
	        
	        HttpGet req = new HttpGet(uri);
	        HttpResponse response = client.execute(req);
			String json = getResponse(response);
			return new JSONObject(json);
		} catch (Exception e) {
			return null;
		}
	}  
	
	public void delete(String id){
			
		try {
			String search = getApiUrl() + "/" + id;
			List<NameValuePair> qparams = new ArrayList<NameValuePair>();
			qparams.add(new BasicNameValuePair("apiKey", apiKey));
			
			URI uri;
			uri = createURI(qparams, search);
			HttpDelete delete = new HttpDelete(uri);
			client.execute(delete);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private String getResponse(HttpResponse response) throws IllegalStateException, IOException{
		
		HttpEntity entity = response.getEntity();
		InputStream in = entity.getContent();
		String json = "";
		String line = "";
		BufferedReader reader = new BufferedReader(new InputStreamReader(in));
		while( (line = reader.readLine()) != null){
			
			json += line;
		}
		return json;
		
	}
	
}
